namespace Wolfpack.Contrib.Tests.Publishers.Deployment
{
    using Core.Testing.Bdd;
    using NUnit.Framework;
    using StoryQ;

    public class NUnitDeploymentPublisherTests : BddFeature
    {
        protected override Feature DescribeFeature()
        {
            return new Story("Testing the nunit deployment publisher")
                .InOrderTo("Ensure the component works correctly")
                .AsA("Downloaded nunit executable package")
                .IWant("To inspect the result messages that are published after the nunit package has executed");
        }

        [Test]
        [Category("Unit")]
        public void SuccessfulTestNoFailures()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("The nunit process completed successfully with some successful tests and no failures")
                    .Given(domain.TheLauncherIndicatesSuccess)
                        .And(domain.TheUnitTestResultContainsNoFailuresErrorsOrInvalidTests)
                        .And(domain.TheAgentIsStarted)
                    .When(domain.ThePublisherIsCalled)
                    .Then(domain.ThereShouldBe_HealthCheckNotificationsReceived, 1)
                        .And(domain.TheFilenameTheParserIsCalledWithIsTheSameAsTheConfig)
                        .And(domain.TheNotificationRecievedAtIndex_ShouldHaveResult_, 1, true)
                        .And(domain.TheDataMessageShouldContainTheTestResultAsProperties)
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "PackageVersion", "9.9.9.9")
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "ResultCode", "0")
                    .ExecuteWithReport();
            }
        }

        [Test]
        [Category("Unit")]
        public void SuccessfulTestWithFailures()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("The nunit process completed successfully with failures")
                    .Given(domain.TheLauncherIndicatesSuccess)
                        .And(domain.TheUnitTestResultFailuresIsSetTo_, 2)
                        .And(domain.TheAgentIsStarted)
                    .When(domain.ThePublisherIsCalled)
                    .Then(domain.TheNotificationRecievedAtIndex_ShouldHaveResult_, 1, false)
                        .And(domain.TheDataMessageShouldContainTheTestResultAsProperties)
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "Failures", "2")
                    .ExecuteWithReport();
            }
        }

        [Test]
        [Category("Unit")]
        public void SuccessfulTestWithErrors()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("The nunit process completed successfully with errors")
                    .Given(domain.TheLauncherIndicatesSuccess)
                        .And(domain.TheUnitTestResultErrorsIsSetTo_, 2)
                        .And(domain.TheAgentIsStarted)
                    .When(domain.ThePublisherIsCalled)
                    .Then(domain.TheNotificationRecievedAtIndex_ShouldHaveResult_, 1, false)
                        .And(domain.TheDataMessageShouldContainTheTestResultAsProperties)
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "Errors", "2")
                    .ExecuteWithReport();
            }
        }

        [Test]
        [Category("Unit")]
        public void SuccessfulTestButConfiguredToPublishOnlyFailures()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("The nunit process completed successfully but the publisher is configured only to report failures")
                    .Given(domain.TheLauncherIndicatesSuccess)
                        .And(domain.ThePublisherShouldOnlyPublishOnFailure)
                        .And(domain.TheUnitTestResultContainsNoFailuresErrorsOrInvalidTests)
                        .And(domain.TheDefaultNotificationFiltersAreLoaded)
                        .And(domain.TheAgentIsStarted)
                    .When(domain.ThePublisherIsCalled)
                    .Then(domain.ThereShouldBe_HealthCheckNotificationsReceived, 0)
                    .ExecuteWithReport();
            }
        }

        [Test]
        [Category("Unit")]
        public void FatalReturnFromNUnitProcess()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("The nunit process terminates with a fatal return code (negative)")
                    .Given(domain.TheLauncherReturnsErrorCode_, -1)
                        .And(domain.TheAgentIsStarted)
                    .When(domain.ThePublisherIsCalled)
                    .Then(domain.ThereShouldBe_HealthCheckNotificationsReceived, 1)
                        .And(domain.TheNotificationRecievedAtIndex_ShouldHaveResult_, 1, false)
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "PackageVersion", "9.9.9.9")
                        .And(domain.TheCheckNotificationShouldHaveProperty_WithValue_, "ResultCode", "-1")
                    .ExecuteWithReport();
            }
        }

        [Test]
        [Category("Unit")]
        public void TestResultXmlFileParserHappyPath()
        {
            using (var domain = new NUnitDeploymentPublisherDomain())
            {
                Feature.WithScenario("A well formed nunit test result xml file should be parsed")
                    .Given(domain.TheXmlFileParserWithResultFile, @"TestData\Deployment\results-ok.xml")
                        .And(domain.TheAgentIsStarted)
                    .When(domain.TheParserIsInvoked)
                    .Then(domain.TheUnitResultShouldBeValid)
                        .And(domain.TheUnitTestResultShouldHave_Total, 1)
                        .And(domain.TheUnitTestResultShouldHave_Errors, 2)
                        .And(domain.TheUnitTestResultShouldHave_Failures, 3)
                        .And(domain.TheUnitTestResultShouldHave_NotRun, 4)
                        .And(domain.TheUnitTestResultShouldHave_Inconclusive, 5)
                        .And(domain.TheUnitTestResultShouldHave_Ignored, 6)
                        .And(domain.TheUnitTestResultShouldHave_Skipped, 7)
                        .And(domain.TheUnitTestResultShouldHave_Invalid, 8)
                    .ExecuteWithReport();
            }
        }
    }
}